#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <signal.h>

#include <analex_pcod.h>
#include <pile.h>

#define PLUS 	0 // +
#define MOINS 	1 // -
#define MULTI 	2 // *
#define DIV 	3 // /
#define SINF 	4 // <
#define INFOE 	5 // <=
#define SSUP 	6 // >
#define SUPOE	7 // >=
#define DIF 	8 // <>
#define EGAL 	9 // =

#define d(X) printf("%s\n",X);fflush(stdout)

int u_type;
char u_lex[80];

char operateur[80];
char param1[80];
char param2[80];

bool flag;
bool isPointArret = 0;
int compteur_ordinal = 0;
int numero_instruction = 0;
char ri[256];

FILE *pcod;
int finprogram;
int lignecourante;

//buffer pour communiquer avec l'interface tcl
char buf[80];
bool stop = true;

int* lst_point_arret = NULL;
int taille_lst_point_arret;

/*
 * Structure utilisé pour le stockage d'une variable de la table des symboles
 */
typedef struct Variable Variable;
struct Variable {
	char nom_var[80];
	char type_var[80];
};

Variable** table_symbole = NULL;
int taille_table_symbole = 0;

void DEBUG(char *s) {
	printf("debug : %s\n", s);
	fflush(stdout);
}

bool lex_type(int z){

	if((u_type = yylex()) == z){
		return true;
	}

	return false;
}

void close_program() {
	
	if (pcod != NULL)
		fclose(pcod);
	pcod = NULL;
	
	if (lst_point_arret != NULL)
		free(lst_point_arret);
	lst_point_arret = NULL;
	
	if (taille_table_symbole > 0) {
		int i;
		for (i=0; i < taille_table_symbole; i++) {
			free(table_symbole[i]);
		}
		free(table_symbole);
	}
	
	taille_table_symbole = 0;
	
	compteur_ordinal = 0;
	stop = true;
}

void init_table_symbole() {
	taille_table_symbole = 0;
	
	u_type = yylex();
	
	// on calcul le nombre d'élément dans la table des symboles
	while (u_type != 0) {
		if (u_type == TABLE_SYMBOLE)
			taille_table_symbole++;
		u_type = yylex();
	}
	
	fseek(pcod, 0, SEEK_SET);
	yyrestart(pcod);
	
	u_type = yylex();
	
	//on parcours la table des symboles et on enregistre les variables ainsi que
	//leur type
	if (taille_table_symbole > 0) {
		
		table_symbole = malloc(taille_table_symbole * sizeof(Variable));
	
		if (table_symbole == NULL) {
			perror("memoire insuffisante");
			exit(5);
		}
	
		int i = 0;
		
		while (u_type != 0) {
		
			if (u_type == TABLE_SYMBOLE) {
			
				Variable* v  = malloc(sizeof(Variable));
			
				if (v == NULL) {
					perror("memoire insuffisante");
					exit(6);
				}
			
				lex_type(CHAINE_TABLE_SYMBOLE);
				strcpy(v->nom_var, u_lex);
				lex_type(CHAINE_TABLE_SYMBOLE);
				strcpy(v->type_var, u_lex);
	
				table_symbole[i++] = v;
			
			}
		
			u_type = yylex();
		}
		
	}
	
	fseek(pcod, 0, SEEK_SET);
	yyrestart(pcod);
	
}

void afficher_table_symbole() {
	int i;
	
	for (i=0; i < taille_table_symbole; i++) {
		printf("%s : %s\n", (table_symbole[i])->nom_var, (table_symbole[i])->type_var);
	}
	
}

void pileToTCL() {

	afficher_table_symbole();
	
	char pile[1024];
	
	strcpy(pile, "stac:");
	
	Pile *p = getBase();
	
	int i = 0;
	while (p != NULL) {
		if (i > taille_table_symbole-1) {
			char c[80];
			void * pVal = p->ptr_val;
			
			if(p->type == 1){
				strcat(pile, "int$");
				int * var_int = (int *) pVal;
				sprintf(c, "%d", *var_int);
			}else if(p->type == 2){
				strcat(pile, "double$");
				double * var_double = (double *) pVal;
				sprintf(c, "%f", *var_double);
			}else if(p->type == 3){
				strcat(pile, "bool$");
				int * var_int = (int *) pVal;
				sprintf(c, "%d", *var_int);
			}else if(p->type == 4){
				strcat(pile, "char$");
				char *oo = (char *) pVal;
				sprintf(c, "%c", *oo);
			}else if(p->type == 5){
				strcat(pile, "string$");
				char* oo = (char *) pVal;
				sprintf(c, "%s", oo);
			}
			strcat(pile, c);
			strcat(pile, "$");
		} else {
			strcat(pile, (table_symbole[i])->type_var);
			strcat(pile, " ");
			strcat(pile, (table_symbole[i])->nom_var);
			strcat(pile, "$");
			
			void * pVal = p->ptr_val;
			
			char c[80];
			if (strcmp( (table_symbole[i])->type_var+1, "_int") == 0 || strcmp( (table_symbole[i])->type_var+1, "_bool") == 0) {
				int * var_int = (int *) pVal;
				sprintf(c, "%d", *var_int);
			} else if(strcmp( (table_symbole[i])->type_var+1, "_double") == 0) {
				double * var_double = (double *) pVal;
				sprintf(c, "%f", *var_double);
			} else if(strcmp( (table_symbole[i])->type_var+1, "_char") == 0) {
				char *oo = (char *) pVal;
				sprintf(c, "%c", *oo);
			} else if(strcmp( (table_symbole[i])->type_var+1, "_string") == 0) {
				char* oo = (char *) pVal;
				sprintf(c, "%s", oo);
			}
			strcat(pile, c);
			strcat(pile, "$");
		}
		++i; p = p->suiv;
	}
	
	printf("%s\n", pile);
	fflush(stdout);
}

int traite_message_tcl() {

	
	int firstexec = 1;
	
	for (;;) {
		
		scanf("%s", &buf);
		
		if (strncmp(buf, "open:", 5) == 0) {
			
			firstexec = 1;
			close_program();
			
			if (pcod != NULL)
				fclose(pcod); 
			
			printf("!%s!\n", buf+5);
			fflush(stdout);
			
			pcod = fopen(buf+5, "r");
			
			if (pcod == NULL) {
				perror("FOPEN");
				exit(2);
			}
			
			yyin = pcod;

			continue;
		}
		
		if (pcod != NULL) {

			if (strncmp(buf, "quit:", 5) == 0) {
				close_program();
			}

			else if (strncmp(buf, "poar:", 5) == 0) {
				init_point_arret();
			}
		
			else if (strncmp(buf, "inpu:", 5) == 0) {
				//traite_read();
			}
		
			else if (strncmp(buf, "exec:", 5) == 0) {
				printf("!%s!\n", buf);
				fflush(stdout);	
				stop = false;
				
				execution:
				finprogram = 0;
				if(firstexec ==1){
					printf("wril:\n");
					printf("wril:>> Debut du programme\n");
					initBase();
					init_table_symbole();
					lex_type(NUM_LIGNE);
					firstexec=0;
					strcpy(ri, u_lex);
				}
		
				int finpgm ;

				for(;;) {
					
					lignecourante = atoi(u_lex);
					
					lex_type(OPERATEUR);
					strcpy(operateur, u_lex);
					strcat(ri, " ");
					strcat(ri, u_lex);

					lex_type(PARAMETRE);
					strcpy(param1, u_lex);
					strcat(ri, " ");
					strcat(ri, u_lex);
					
					lex_type(VIRGULE);
					strcat(ri, u_lex);
	
					lex_type(PARAMETRE);
					strcpy(param2, u_lex);
					strcat(ri, u_lex);
					
					finpgm = traite_instruction();

					if (u_type == PARAMETRE)
						u_type = yylex();
		
					if (u_type == COMMENTAIRE)
						yylex();
						
					strcpy(ri, u_lex);	
					if(finpgm == 0)
						break;
		
				}
				
				if(finprogram==1){
					supprimer_pile();
					init_table_symbole();
					firstexec=1;
					numero_instruction = 0;
					compteur_ordinal = 0;
				}

			}
		
			else if (strncmp(buf, "next:", 5) == 0)  {
				stop = true;
				goto execution;
			} 	
			
		}
		
	}
		
	return 1;
}

Pile* getElementAt(int deplacement) {
	
	Pile* p = getBase();	
	
	int i;
	for (i=0; i++ < deplacement; p = p->suiv);
	
	return p;
}

void verif_compteur_ordinal() {
	
	if (numero_instruction != compteur_ordinal) {
		
		numero_instruction = compteur_ordinal;
		
		fseek(pcod, 0, SEEK_SET);
		yyrestart(pcod);
		
		int num_ligne;
		
		for(;;) {
		
			u_type = yylex();
			
			if (u_type == NUM_LIGNE) {
				
				num_ligne = atoi(u_lex);
				
				if (num_ligne == compteur_ordinal)
					break;
			}
		}
		
	} else {
		u_type = yylex();
	}
	
}

void init_point_arret() {

	taille_lst_point_arret = 0;
	if(lst_point_arret !=NULL)
		free(lst_point_arret);
	lst_point_arret =NULL;	
	lst_point_arret = malloc(sizeof(int)*80);
	
	int longueur = strlen(buf);
	
	
	//il y a au moins un point d'arret
	if (longueur > 5) {
	
		int i; int val = 0;
		if(buf[5]>='0' && buf[5]<='9'){
			for(i=5;i<longueur;++i){
				if(buf[i]>='0' && buf[i]<='9'){
					char c[2]; c[1] = '\0'; c[0]=buf[i];
					val = val*10+atoi(c);
				}else{
					lst_point_arret[taille_lst_point_arret++] = val;
					val = 0;
				}
			
			}
		}	
	}
	
	
}

int verif_point_arret() {
	
	int i;
	int r;
	
	for (i=0; i < taille_lst_point_arret && stop == false; i++) {
		if (lignecourante == lst_point_arret[i]) {
			stop = true;
		} 
	}

	if (stop == true) {
		pileToTCL();
		printf("linb:%d\n", numero_instruction);
		fflush(stdout);
		printf("flag:%d\n", flag);
		fflush(stdout);
		printf("coor:%d\n", compteur_ordinal);
		fflush(stdout);
		printf("riii:%s\n", ri);
		fflush(stdout);
		return 0;
	}
	
	stop = false;
	
	return 1;
}

void affiche_point_arret() {
	
	int i;
		printf("PA:");	
		printf("%d\n", taille_lst_point_arret);
	for (i=0; i < taille_lst_point_arret; i++) {
		printf("%d ",lst_point_arret[i]);
	}
	printf("\n");
}

void traite_inc() {
	int type = atoi(param1);
	
	switch(type) {
		case INT: {
			int i;
			push(INT, (void *)&i);
			break;
		}
		case DOUBLE: {
			double d;
			push(DOUBLE, (void *)&d);
			break;
		}
		case BOOLEAN: {
			bool b;
			push(BOOLEAN, (void *)&b);
			break;
		}
		case CHARACTER: {
			char c;
			push(CHARACTER, (void *)&c);
			break;
		}
		case STRING: {
			char c[1];
			c[0] = '\0';
			push(STRING, (void *)&c);
			break;
		}
	}

}

void traite_lod() {
	
	int type = atoi(param1);
	int position = atoi(param2);
	Pile* p = getElementAt(position);

	switch(type) {
		case INT: {
			push(INT, p->ptr_val);
			break;
		}
		case DOUBLE: {
			push(DOUBLE, p->ptr_val);
			break;
		}
		case BOOLEAN: {
			push(BOOLEAN, p->ptr_val);
			break;
		}
		case CHARACTER: {
			char *c = (char *) p->ptr_val;
			char r = *c;
			push(CHARACTER, p->ptr_val);
			break;
		}
		case STRING: {
			push(STRING, p->ptr_val);
			break;
		}
	}
}

void traite_sto() {	
	int type = atoi(param1);
	int position = atoi(param2);
	
	int a;
	
	void * val = pop(&a);
	Pile* p = getElementAt(position);
	p->ptr_val = val;
	
	switch(type) {
		case INT: {
			p->type = 1;
			break;
		}	
		case DOUBLE: {
			p->type = 2;
			break;
		}
		case BOOLEAN: {
			p->type = 3;
			break;
		}
		case CHARACTER: {
			p->type = 4;
			break;
		}
		case STRING: {
			p->type = 5;
			break;
		}		
	}
	
}

void traite_opr() {
 	
 	int code_operation = atoi(param2);

	int type_operande1;
	int type_operande2;
	
	int type_resultat;

	void *operande2 = pop(&type_operande2);
	void *operande1 = pop(&type_operande1);
	
	if (type_operande1 == DOUBLE || type_operande2 == DOUBLE)
		type_resultat = DOUBLE;
	else if(type_operande1 == INT && type_operande2 == INT)
		type_resultat = INT;
	else if(type_operande1 == BOOLEAN && type_operande2 == BOOLEAN)
		type_resultat = BOOLEAN;
	else
		type_resultat = STRING;
	
 	switch(code_operation) {
 		/* + */
 		case 0:
 			
 			switch(type_resultat) {
 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 + *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						double res = *res_op1 + *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 + *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					int res = *res_op1 + *res_op2;
					
					push(INT, (void *)&res);

 					break;
 				}
 				
 				case STRING: {
 					
 					if (type_operande1 == CHARACTER || type_operande2 == CHARACTER) { 
	 				
	 					if (type_operande1 == CHARACTER) {
	 						
	 						char *res_op1 = (char *) operande1;
							
							if (type_operande2 == CHARACTER) {
								
								char *res_op2 = (char *) operande2;
								
								char str[3];
								str[0] = *res_op1;
								str[1] = *res_op2;
								str[2] = '\0';
		
								push(STRING, (void *)str);
								
							} else {
								//operande 1 = CHARACTER && operande 2 = STRING
								
								char *res_op1 = (char *) operande1;								
								char *c = (char *) operande2;
								
								int taille = strlen(c) + 1;		
								char *str = malloc(sizeof(char) * taille);
							
								str[0] = *res_op1;
								strcpy(str+1, c);
	
								push(STRING, (void *)str);
								
								free(str);	
							}
	 					} else if (type_operande2 == CHARACTER) {
	 							//operande 1 = STRING && operande 2 = CHARACTER
								
								char *res_op2 = (char *) operande2;								
								char *c = (char *) operande1;
								
								int taille = strlen(c) + 1;		
								char *str = malloc(sizeof(char) * taille);
							
								str[0] = *res_op2;
								strcpy(str+1, c);
	
								push(STRING, (void *)str);
								
								free(str);						
	 					}
	 					
					} else {
					
						char **c1 = (char **) operande1;
						char **c2 = (char **) operande2;
						
						int taille = strlen(c1) + strlen(c2) + 2;
						
						char *str = malloc(sizeof(char) * taille);
						
						strcpy(str, c1);
						strcat(str, c2);
						
						push(STRING, (void *)str);
						
						free(str);
					
					}
 					
 					break;
 				}
 			}
 			
 			break;
 		/* - */
 		case 1:
			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 - *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						double res = *res_op1 - *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 - *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					int res = *res_op1 - *res_op2;
					
					push(INT, (void *)&res);

 					break;
 				}
 				
			}

			break;
 		/* * */
 		case 2:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 * *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						double res = *res_op1 * *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 * *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					int res = *res_op1 * *res_op2;
					
					push(INT, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* / */
 		case 3:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 / *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						double res = *res_op1 / *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						double res = *res_op1 / *res_op2;
 						
 						push(DOUBLE, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					int res = *res_op1 / *res_op2;
					
					push(INT, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* < */
 		case 4:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
						bool res = false;

 						if(*res_op1 < *res_op2)
							res = true;
						 						
 						push(BOOLEAN, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						bool res = false;

 						if(*res_op1 < *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						bool res = false;

 						if(*res_op1 < *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					bool res = false;

					if(*res_op1 < *res_op2)
						res = true;
					
					push(BOOLEAN, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* <= */
 		case 5:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
						bool res = false;

 						if(*res_op1 <= *res_op2)
							res = true;
						 						
 						push(BOOLEAN, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						bool res = false;

 						if(*res_op1 <= *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						bool res = false;

 						if(*res_op1 <= *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					bool res = false;

					if(*res_op1 <= *res_op2)
						res = true;
					
					push(BOOLEAN, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* > */
 		case 6:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
						bool res = false;

 						if(*res_op1 > *res_op2)
							res = true;
						 						
 						push(BOOLEAN, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						bool res = false;

 						if(*res_op1 > *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						bool res = false;

 						if(*res_op1 > *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					bool res = false;

					if(*res_op1 > *res_op2)
						res = true;
					
					push(BOOLEAN, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* >= */
 		case 7:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
						bool res = false;

 						if(*res_op1 >= *res_op2)
							res = true;
						 						
 						push(BOOLEAN, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						bool res = false;

 						if(*res_op1 >= *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						bool res = false;

 						if(*res_op1 >= *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op2 = (int *) operande1;
					int *res_op1 = (int *) operande2;
					
					bool res = false;

					if(*res_op1 >= *res_op2)
						res = true;
					
					push(BOOLEAN, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* <> */
 		case 8:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
						bool res = false;

 						if(*res_op1 != *res_op2)
							res = true;
						 						
 						push(BOOLEAN, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						bool res = false;

 						if(*res_op1 != *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						bool res = false;

 						if(*res_op1 != *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					bool res = false;

					if(*res_op1 != *res_op2)
						res = true;
					
					push(BOOLEAN, (void *)&res);

 					break;
 				}
 			
			}

			break;
 		/* = */
 		case 9:
 			switch(type_resultat) {

 				case DOUBLE: {
 					
 					if (type_operande1 == INT) {
 						int *res_op1 = (int *) operande1;
 						double *res_op2 = (double *) operande2;
 						
						bool res = false;

 						if(*res_op1 == *res_op2)
							res = true;
						 						
 						push(BOOLEAN, (void *)&res);
 					} else if (type_operande2 == INT) {
 						double *res_op1 = (double *) operande1;
 						int *res_op2 = (int *) operande2;
 						
 						bool res = false;

 						if(*res_op1 == *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					} else {
 						double *res_op1 = (double *) operande1;
 						double *res_op2 = (double *) operande2;
 						
 						bool res = false;

 						if(*res_op1 == *res_op2)
							res = true;
 						
 						push(BOOLEAN, (void *)&res);
 					}
 					
 					break;
 				}
 				
 				case INT: {
 				
 					int *res_op1 = (int *) operande1;
					int *res_op2 = (int *) operande2;
					
					bool res = false;

					if(*res_op1 == *res_op2)
						res = true;
					
					push(BOOLEAN, (void *)&res);

 					break;
 				}
 			
			}

			break;
 	}

}

void traite_lit() {
	
	int type = atoi(param1);
	
	switch(type) {
		case INT: {
			int variable = atoi(param2);
			push(INT, (void *)&variable);
			break;
		}
		case DOUBLE: {
			double variable = atof(param2);
			push(DOUBLE, (void *)&variable);
			break;
		}
		case BOOLEAN: {
			bool variable = atoi(param2);
			push(BOOLEAN, (void *)&variable);
			break;
		}
		case CHARACTER: {
			char c = param2[1];
			push(CHARACTER, (void *)&c);
			break;
		}
		case STRING: {
			push(STRING, (void *)param2);	
			break;
		}
	}
}

void traite_stp() {	
	pileToTCL();
	printf("wril:\n");
	printf("wril:>> Fin du programme\n");

		
	printf("linb:%d\n", numero_instruction);
	fflush(stdout);
	printf("flag:%d\n", flag);
	fflush(stdout);
	printf("coor:%d\n", compteur_ordinal);
	fflush(stdout);
	printf("riii:%s\n", ri);
	fflush(stdout);
	fflush(stdout);
}

void traite_sfl() {
	//set flag
	int type;
	void *sommet = pop(&type);
	
	bool *b = (bool *) sommet;
	
	flag = *b;
}

void traite_jmp() {
	compteur_ordinal = atoi(param2); 
}

void traite_jpc() {
	if (flag == 0) {
		compteur_ordinal = atoi(param2); 
	}
}

void traite_cal() {
	push(INT, (void *)&compteur_ordinal);
	traite_jmp();
}

void traite_nop() {
}

void traite_lba() {
	//pour les fonctions
}

void traite_sta() {
	//pour les fonctions
}

void traite_ret() {
	int type;
	void * val  = pop(&type);
	int *n = (int *) val;
	compteur_ordinal = *n;
}

void traite_rea(char * typeC) {
	printf("inpu:\n");
	fflush(stdout);
	
	char res[128];
	
	for (;;) {
		scanf("%s", &res);
		if (strncmp(res, "inpu:", 5) == 0) {
			break;
		}
	}
	
	int type = atoi(typeC);
	
	switch(type) {
		case INT: {
			int val = atoi(res+5);
			push(INT, (void *)&val);
			break;
		}
		case DOUBLE: {
			double val = atof(res+5);
			push(DOUBLE, (void *)&val);
			break;
		}
		case BOOLEAN: {
			bool val = atoi(res+5);
			push(BOOLEAN, (void *)&val);
			break;
		}
		case CHARACTER: {
			char c = res[5];
			push(CHARACTER, (void *)&c);
			break;
		}
		case STRING: {
			push(STRING, (void *)res+5);	
			break;
		}
	}
	

}

void traite_wrt() {
	int type;
	void * pVal  = pop(&type);
	
	char message[128];
	
	strcpy(message, "writ:");
	
	char c[80];
	
	if(type == 1){
		int * var_int = (int *) pVal;
		sprintf(c, "%d", *var_int);
	}else if(type == 2){
		double * var_double = (double *) pVal;
		sprintf(c, "%f", *var_double);
	}else if(type == 3){
		int * var_int = (int *) pVal;
		sprintf(c, "%d", *var_int);
	}else if(type == 4){
		char *oo = (char *) pVal;
		sprintf(c, "%c", *oo);
	}else if(type == 5){
		char* oo = (char *) pVal;
		sprintf(c, "%s", oo);
	}
	
	strcat(message, c);
	fflush(stdout);
	printf("%s\n",message);
	fflush(stdout);
	fflush(stdout);
}

void traite_wrl() {
	int type;
	void * pVal  = pop(&type);
	
	char message[128];
	
	strcpy(message, "wril:");
	
	char c[80];
	
	if(type == 1){
		int * var_int = (int *) pVal;
		sprintf(c, "%d", *var_int);
	}else if(type == 2){
		double * var_double = (double *) pVal;
		sprintf(c, "%f", *var_double);
	}else if(type == 3){
		int * var_int = (int *) pVal;
		sprintf(c, "%d", *var_int);
	}else if(type == 4){
		char *oo = (char *) pVal;
		sprintf(c, "%c", *oo);
	}else if(type == 5){
		char* oo = (char *) pVal;
		sprintf(c, "%s", oo);
	}
	
	strcat(message, c);
	
	fflush(stdout);
	printf("%s\n",message);
	fflush(stdout);
	fflush(stdout);
}

int traite_instruction() {
	
	numero_instruction++;
	compteur_ordinal++;

	if (strcmp(operateur, "INC") == 0)
		traite_inc();
	else if (strcmp(operateur, "LOD") == 0)
		traite_lod();
	else if (strcmp(operateur, "STO") == 0)
		traite_sto();
	else if (strcmp(operateur, "OPR") == 0)
		traite_opr();	
	else if (strcmp(operateur, "LIT") == 0)
		traite_lit();
	else if (strcmp(operateur, "STP") == 0){
		traite_stp();
		finprogram=1;
		return 0;
	}
	else if (strcmp(operateur, "SFL") == 0)
		traite_sfl();
	else if (strcmp(operateur, "JPC") == 0)
		traite_jpc();
	else if (strcmp(operateur, "JMP") == 0)
		traite_jmp();
	else if (strcmp(operateur, "CAL") == 0)
		traite_cal();
	else if (strcmp(operateur, "NOP") == 0)
		traite_nop();
	else if (strcmp(operateur, "LBA") == 0)
		traite_lba();
	else if (strcmp(operateur, "STA") == 0)
		traite_sta();
	else if (strcmp(operateur, "RET") == 0)
		traite_ret();
	else if (strcmp(operateur, "REA") == 0)
		traite_rea(param1);
	else if (strcmp(operateur, "WRT") == 0)
		traite_wrt();
	else if (strcmp(operateur, "WRL") == 0)
		traite_wrl();
	else {
		close_program();
		printf("instruction inconnue\n");
		exit(2);
	}
	
	if(verif_point_arret()==0){
		return 0;
	}
	
	verif_compteur_ordinal();
	
	return 1;
	
}


